package com.youlu.campus.service.aomen;

import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
//import com.ctrip.framework.apollo.Config;
//import com.ctrip.framework.apollo.ConfigService;
import com.youlu.campus.common.utils.HttpClientUtil;
import com.youlu.campus.entity.SystemApolloConfig;
import com.youlu.campus.entity.UserParticipateActivityInfo;
import com.youlu.campus.entity.VO.req.AoMenActivityDataSyncConfigReq;
import com.youlu.campus.entity.aomen.AoMenAccessToken;
import com.youlu.campus.service.system.SystemApolloConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 澳门回归活动-第三方
 * 同步手机号服务
 * 获取token
 */
@Slf4j
@Service
public class AoMenService {

    @Value("${aomen.appId}")
    private String appId;

    @Value("${aomen.appSecret}")
    private String appSecret;

    @Value("${aomen.domain}")
    private String domain;

    @Value("${aomen.redirectUriCoupon}")
    private String redirectUriCoupon;

    @Value("${aomen.redirectUriContest}")
    private String redirectUriContest;

    @Value("${aomen.domainRedirectPage}")
    private String domainRedirectPage;

    /**
     * 获取AccessToken接口
     */
    private final static String TOKEN_INTERFACE_URL = "/openapi/oauth/getAccessToken";

    /**
     * 推送会员手机号
     */
    private final static String PHONE_INTERFACE_URL = "/openapi/user/push";

    private final static String AREA_CODE = "86";

    private final static String AES = "";

    private final static String publicKey =
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMTrADXMR8FMQus6Uu0yZIsrYnRVL6qqghcrFgHgSj3H3C40VwwcVN321V0l9AAsT3ZMjVbtko2m2by5WdPGzwRHrlLXvSh4hg+rRdZn7q39S7L0Ih0/H+gbTPMaEniUABXto3AETWSU4PUDGXUTDngE3kZeFgWZn1x8IjXl9AoQIDAQAB";

    @Resource(name = "masterMongoTemplate")
    private MongoTemplate masterMongoTemplate;

    @Autowired
    private SystemApolloConfigService systemApolloConfigService;

    @Async
    public void doPushUserPhone(String phone, String activityId, String userId) {
//        Config config = ConfigService.getAppConfig();
//        String cnf = config.getProperty("activity.data.snyc", "{}");
//        if (StringUtils.isBlank(cnf)) {
//            log.warn("【万博荟】AoMenService.doPushUserPhone 无需推送 push appId ->{} | phone->{}", appId, phone);
//            return;
//        }
//        AoMenActivityDataSyncConfigReq activityDataSyncConfigReq = JSON.parseObject(cnf,
//                AoMenActivityDataSyncConfigReq.class);
        SystemApolloConfig systemApolloConfig = systemApolloConfigService.find();
        AoMenActivityDataSyncConfigReq activityDataSyncConfigReq=systemApolloConfig.getAoMenActivityDataSyncConfigReq();
        if (Objects.isNull(activityDataSyncConfigReq) || !activityDataSyncConfigReq.getSync()) {
            log.warn("【万博荟】AoMenService.doPushUserPhone 无需推送 push appId ->{} | phone->{}", appId, phone);
            return;
        }
        if (!activityId.equals(activityDataSyncConfigReq.getActivityId())) {
            log.warn("【万博荟】AoMenService.doPushUserPhone 无需推送活动ID不支持 push appId ->{} | phone->{}", appId, phone);
            return;
        }
        log.info("【万博荟】AoMenService.doPushUserPhone start push appId ->{} | phone->{}", appId, phone);
        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken错误 appId ->{}", appId);
            return;
        }
        Long count = incAoMenCount(activityId, 0);
        if (activityDataSyncConfigReq.getMaxCount() > count) {
            Integer randomMax = activityDataSyncConfigReq.getRandomMax();
            int randomCount = ThreadLocalRandom.current().nextInt(randomMax);
            if (randomCount > activityDataSyncConfigReq.getLimitCount()) {
                log.error("【万博荟】AoMenService.doPushUserPhone 超过推送设置比例不推送 randomMax ->{}| randomCount ->{}", randomMax, randomCount);
                return;
            }
        }
        RSA publicRsa = new RSA(null, publicKey);
        String encryptPhone = publicRsa.encryptBase64(phone, KeyType.PublicKey);
        System.out.println("数据密文：" + encryptPhone);
        Map<String, Object> paramMap = new HashMap(3);
        paramMap.put("appId", appId);
        paramMap.put("areaCode", AREA_CODE);
        paramMap.put("phone", encryptPhone);
        String formUrl = domain + PHONE_INTERFACE_URL;
        try {
            Map<String, Object> headMap = new HashMap(1);
            headMap.put("token", accessToken);
            String result = HttpClientUtil.postForm(formUrl, paramMap, headMap, 3000, "utf8", 3, true);
            log.info("【万博荟】AoMenService.doPushUserPhone 推送返回结果 appId ->{} | phone->{} | result->{}", appId, phone,
                    result);
            if (StringUtils.isBlank(result)) {
                log.error("【万博荟】AoMenService.doPushUserPhone 推送返回结果失败 appId ->{} | phone->{} ", appId, phone);
                return;
            }
            AoMenResult<AoMenUserInfo> aoMenResult = JSON.parseObject(result,
                    new TypeReference<AoMenResult<AoMenUserInfo>>() {
                    });
            if (Objects.isNull(aoMenResult)) {
                log.error("【万博荟】AoMenService.doPushUserPhone 推送返回结果失败 appId ->{} | phone->{} ", appId, phone);
                return;
            }
            if (AoMenResult.SUCCESS_CODE != aoMenResult.getCode()) {
                log.info("【万博荟】AoMenService.doPushUserPhone 推送返回结果 appId ->{} | phone->{} | result_code->{}| " +
                                "result_msg ->{}", appId,
                        phone, aoMenResult.getCode(), aoMenResult.getMessage());
                return;
            }
            AoMenUserInfo aoMenUserInfo = aoMenResult.getData();
            if (Objects.isNull(aoMenUserInfo)) {
                log.error("【万博荟】AoMenService.doPushUserPhone 推送返回结果获取用户openId 为空 appId ->{} | phone->{} ", appId,
                        phone);
                return;
            }
            String openId = aoMenUserInfo.getOpenId();
            Query query = new Query();
            query.addCriteria(Criteria.where("userId").is(userId));
            query.addCriteria(Criteria.where("activityId").is(activityId));
            Update update = new Update();
            update.set("otherPlatformOpenId", openId);
            update.set("updatedTime", new Date());
            this.masterMongoTemplate.updateFirst(query, update, UserParticipateActivityInfo.class);
            incAoMenCount(activityId, 1);
            log.info("【万博荟】AoMenService.doPushUserPhone success openId ->{} appId ->{} | phone->{} ", openId, appId,
                    phone);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("【万博荟】AoMenService.doPushUserPhone 推送返回结果失败 appId ->{} | phone->{} ", appId, phone, e);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("【万博荟】AoMenService.doPushUserPhone 推送返回结果失败 appId ->{} | phone->{} ", appId, phone,
                    e);
        }
        log.info("【万博荟】AoMenService.doPushUserPhone end push appId ->{} | phone->{} 结束", appId, phone);
    }

    /**
     * 获取AccessToken
     *
     * @return
     */
    public String getAccessToken() {
        String accessToken = getAccessTokenByAppId(appId);
        if (StringUtils.isNotBlank(accessToken)) {
            log.info("【万博荟】AoMenService.getAccessToken appId ->{} | accessToken->{} db存在", appId, accessToken);
            return accessToken;
        }
        Map<String, Object> paramMap = new HashMap(2);
        paramMap.put("appId", appId);
        paramMap.put("appSecret", appSecret);
        try {
            String result = HttpClientUtil.get(domain + TOKEN_INTERFACE_URL, paramMap, null, 3000, "utf-8", 3, true);
            log.info("【万博荟】AoMenService.getAccessToken appId ->{} | result->{}", appId, result);
            if (StringUtils.isBlank(result)) {
                log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken错误 appId ->{}", appId);
                return "";
            }
            AoMenResult<String> aoMenResult = JSON.parseObject(result, new TypeReference<AoMenResult<String>>() {
            });
            if (Objects.isNull(aoMenResult)) {
                log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken错误 appId ->{}", appId);
                return "";
            }
            if (aoMenResult.SUCCESS_CODE != aoMenResult.getCode()) {
                log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken错误 appId ->{} | result_code ->{} | " +
                        "result_msg - >{}", appId, aoMenResult.getCode(), aoMenResult.getMessage());
                if (aoMenResult.NO_AUTHORIZATION == aoMenResult.getCode()) {
                    log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken 过期 appId ->{} | result_code ->{} | " +
                            "result_msg - >{}", appId, aoMenResult.getCode(), aoMenResult.getMessage());
                    //getAccessToken();
                }
                return "";
            }
            accessToken = aoMenResult.getData();
            log.info("【万博荟】AoMenService.getAccessToken appId ->{} | accessToken->{}", appId, accessToken);
            Query query = new Query();
            query.addCriteria(Criteria.where("appId").is(appId));
            Update update = new Update();
            Date now = new Date();
            update.set("accessToken", accessToken);
            update.setOnInsert("createdTime", now);
            update.set("updatedTime", now);
            update.set("accessTokenExpireTime", now);
            FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
            findAndModifyOptions.upsert(Boolean.TRUE);
            findAndModifyOptions.returnNew(Boolean.TRUE);
            this.masterMongoTemplate.findAndModify(query, update, findAndModifyOptions, AoMenAccessToken.class);
            return accessToken;
        } catch (IOException e) {
            e.printStackTrace();
            log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken错误", e);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken错误", e);
        } catch (Exception e) {
            log.error("【万博荟】AoMenService.getAccessToken 获取getAccessToken错误", e);
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 活动签到获取用户拼接
     *
     * @param openId
     * @return
     */
    public String getRedirectUriCoupon(String openId) {
        if (StringUtils.isBlank(openId)) {
            return "";
        }
        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            return "";
        }
        return domainRedirectPage + "/pages/public/oauthRedirect?token=" + accessToken + "&openId=" + openId +
                "&redirectUri=" + redirectUriCoupon;
    }

    /**
     * 活动答题用户答题链接
     *
     * @param activityId
     * @param userId
     * @return
     */
    public String getRedirectUriContest(String userId, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        UserParticipateActivityInfo user = this.masterMongoTemplate.findOne(query, UserParticipateActivityInfo.class);
        if (Objects.isNull(user)) {
            return "";
        }
        String openId = user.getOtherPlatformOpenId();
        if (StringUtils.isBlank(openId)) {
            return "";
        }
        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            return "";
        }
        return domainRedirectPage + "/pages/public/oauthRedirect?token=" + accessToken + "&openId=" + openId +
                "&redirectUri=" + redirectUriContest;
    }

    private String getAccessTokenByAppId(String appId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("appId").is(appId));
        query.with(Sort.by(Sort.Direction.DESC, "id"));
        AoMenAccessToken aoMenAccessToken = this.masterMongoTemplate.findOne(query, AoMenAccessToken.class);
        if (Objects.isNull(aoMenAccessToken)) {
            return "";
        }
        return aoMenAccessToken.getAccessToken();
    }

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public Long incAoMenCount(String activityId, int inc) {
        String str = "campus.aomen.activityId:%s.count";
        String aoMenCount = String.format(str, activityId);
        return redisTemplate.opsForValue().increment(aoMenCount, inc);
    }

    public static void main(String[] args) {

        System.out.println(ThreadLocalRandom.current().nextInt(100));
        RSA rsa = new RSA();
        System.out.println(rsa.getPrivateKeyBase64());


        System.out.println("========================");


        System.out.println(rsa.getPublicKeyBase64());
        String privateKey = "";

        String privateKeyBase64 =
                "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMxOsANcxHwUxC6zpS7TJkiytidFUvqqqCFysWAeBKPcfcLjRXDBxU3fbVXSX0ACxPdkyNVu2SjabZvLlZ08bPBEeuUte9KHiGD6tF1mfurf1LsvQiHT8f6BtM8xoSeJQAFe2jcARNZJTg9QMZdRMOeATeRl4WBZmfXHwiNeX0ChAgMBAAECgYBUJ7liuSyJ+7fPkNnijsD/QvW6+VgzvmXg2TBs6hB5OpJm21y4FGjkKbsMlcn8QOfHC7GaEL3MkSSC/vnSuZgZJ3/DDJ7VuUm+GAV9S/z2aVnNFl5eZJfxEY4AUpdFaau0+6HoFZh1KB3iCKP6pIcrMzkLvAjubs5YuGSaKbstTQJBAOfATelzEpv1Buo131l+GWO+ucKvakFUZelS8/T/y4R8xBg7RzvXDiI2jLUHNbrhJ9Df7MkEBKuFrQuFXQ3GQ6cCQQDhr0Wtht0vL8ifS/GXDFibv5vu0jDOiXnRQxWemJPzh8082Dyr7bGw4gX2hHgiLA5zB0rpqcFhd1wo0UIHrYJ3AkEA0cflvviHU91NUR1K/HuFCCFRjcWz7Uc0qSyJ4LDbzSYTa8vdA3H8PUQbwpKwNGYz4IOSl7OndowexFsIjLt36QJAX4MmIgJpqYa3iXNCk4KOHZxCChi6vy4/d+jERZKdSvu2SIHba4f1I78EdwgpL40lsFjtw2YsiWtSfZPSNh2gkQJAJ77X2kZRB0CetE/KfTIufqjqCKh3Rr9JBo0U/MX+9yAoG7ZIc0z/7CGbZ73WX3j4xEpAd+A8zPswcTFDaO/uRg==";
        //SecureUtil.
        String publicKeyBase64 =
                "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMTrADXMR8FMQus6Uu0yZIsrYnRVL6qqghcrFgHgSj3H3C40VwwcVN321V0l9AAsT3ZMjVbtko2m2by5WdPGzwRHrlLXvSh4hg+rRdZn7q39S7L0Ih0/H+gbTPMaEniUABXto3AETWSU4PUDGXUTDngE3kZeFgWZn1x8IjXl9AoQIDAQAB";
        cn.hutool.crypto.asymmetric.RSA publicRsa = new RSA(null,
                publicKeyBase64);
        String encodStr = publicRsa.encryptBase64("18511677883", KeyType.PublicKey);
        System.out.println("数据密文：" + encodStr);
        cn.hutool.crypto.asymmetric.RSA privateRsa = new RSA(privateKeyBase64,
                null);
        String strEncrypt = privateRsa.decryptStr(encodStr, KeyType.PrivateKey);
        System.out.println("解密后明文：" + strEncrypt);
    }
}
